package com.towexin.application.websocket.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.towexin.application.system.domain.User;
import com.towexin.application.system.service.UserService;
import com.towexin.application.websocket.domain.MessageBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;

/**
 * TODO
 * WebSocket 用户上、下线监听
 * @author Towexin
 * @version 1.0
 * @date 2021/8/12 9:09
 */

@Configuration
public class HttpWebSocketHandlerDecoratorFactory implements WebSocketHandlerDecoratorFactory {
    private static final Logger logger = LoggerFactory.getLogger(HttpWebSocketHandlerDecoratorFactory.class);

    private static UserService service;

    private static SimpMessageSendingOperations simpMessageSendingOperations;

    @Autowired
    private void setUserService(UserService userService){
        HttpWebSocketHandlerDecoratorFactory.service = userService;
    }

    @Autowired
    private void setSimpMessageSendingOperations(SimpMessageSendingOperations simpMessageSendingOperations){
        HttpWebSocketHandlerDecoratorFactory.simpMessageSendingOperations = simpMessageSendingOperations;
    }
    /**
     * 配置 webSocket 处理器
     *
     * @param webSocketHandler webSocket 处理器
     * @return webSocket 处理器
     */
    @Override
    public WebSocketHandler decorate(WebSocketHandler webSocketHandler) {
        return new WebSocketHandlerDecorator(webSocketHandler) {
            /**
             * websocket 连接时执行的动作
             * @param session    websocket session 对象
             * @throws Exception 异常对象
             */
            @Override
            public void afterConnectionEstablished(final WebSocketSession session) throws Exception {
                // 输出进行 websocket 连接的用户信息
                if (session.getPrincipal() != null) {
                    String username = session.getPrincipal().getName();
                    logger.info("用户: [{}] 上线", username);
                    User user = new User();
                    user.setOnline(Boolean.TRUE);
                    service.update(user, new QueryWrapper<User>().eq("username", username));

                    MessageBody messageBody = new MessageBody();
                    messageBody.setFrom("system");
                    messageBody.setContent(service.getNickNameByUserName(username) + " 上线了");
                    messageBody.setTargetUser("all-user");
                    // 公共频道发送
                    simpMessageSendingOperations.convertAndSend("/notify/system/public", messageBody);

                    super.afterConnectionEstablished(session);
                }
            }

            /**
             * websocket 关闭连接时执行的动作
             * @param session websocket session 对象
             * @param closeStatus 关闭状态对象
             * @throws Exception 异常对象
             */
            @Override
            public void afterConnectionClosed(final WebSocketSession session, CloseStatus closeStatus) throws Exception {
                // 输出关闭 websocket 连接的用户信息
                if (session.getPrincipal() != null) {
                    String username = session.getPrincipal().getName();
                    logger.info("用户: [{}] 下线", username);
                    User user = new User();
                    user.setOnline(Boolean.FALSE);
                    service.update(user, new QueryWrapper<User>().eq("username", username));

                    MessageBody messageBody = new MessageBody();
                    messageBody.setFrom("system");
                    messageBody.setContent("user-out");
                    messageBody.setTargetUser("all-user");
                    // 公共频道发送
                    simpMessageSendingOperations.convertAndSend("/notify/system/public", messageBody);

                    super.afterConnectionClosed(session, closeStatus);
                }
            }
        };
    }

}
